package tcp

import (
	"ams/dao"
	"fmt"
	"github.com/sirupsen/logrus"
	"lib/structs/ams"
	"net"
	"sync"
	"time"
)

var tcpServer *Server

type Server struct {
	clientMap sync.Map
}

func InitTcpServer(addr string) (err error) {
	tcpServer = &Server{}
	go func() {
		err = tcpServer.start(addr)
		if err != nil {
			logrus.Errorf("InitTcpServer err:[%v]", err)
		}
	}()

	go func() {
		ticker := time.NewTicker(time.Duration(ams.TcpHeartbeatInterval) * time.Second)
		defer ticker.Stop()
		for range ticker.C {
			// 给全部设备发送心跳信息
			tcpServer.WriterAll(ams.TcpInstruction{
				InsCode: ams.InsCode.Ping,
			})
			// 检查超时没给服务发送心跳的设备
			dao.OnlineMap.Range(func(key, value interface{}) bool {
				t1 := value.(int64)
				if time.Now().Unix()-t1 > ams.TcpHeartbeatInterval*2 {
					dao.OnlineMap.Delete(key)
				}
				return true
			})

		}
	}()
	return nil
}

func (s *Server) start(addr string) error {
	listener, err := net.Listen("tcp", addr)
	defer listener.Close()
	if err != nil {
		logrus.Errorf("启动tcp监听：[%s] 失败,err：[%v]", addr, err)
		return err
	}
	logrus.Infof("Tcp Server start :[%v]", addr)
	for {
		var con net.Conn
		con, err = listener.Accept()
		if err != nil {
			logrus.Errorf("客户端连接失败：[%v]", err)
			continue
		}
		client := newClient(con)
		go client.readLoop()
		go client.writeLoop()
		go client.handleMsg()

		// 发送基础参数，例如举手 等等
		client.connInit()
	}
}

func (s *Server) IsExistClient(uniqueCode string) bool {
	_, exists := s.clientMap.Load(uniqueCode)
	return exists
}

func Writer(uniqueCode string, in ams.TcpInstruction) (err error) {
	if val, ok := tcpServer.clientMap.Load(uniqueCode); ok {
		val.(*Client).Writer(in)
	} else {
		err = fmt.Errorf("client off")
	}
	return err
}

func (s *Server) WriterAll(in ams.TcpInstruction) {
	s.clientMap.Range(func(key, value interface{}) bool {
		value.(*Client).Writer(in)
		return true
	})
}
